/**
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 *
 * The Initial Developer of the Original Code is sephiroth.it
 *
 * Contributor(s):
 *   Gabriele Farina <gabriele@sephiroth.it>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 */
package it.sephiroth.gettext
{
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	import flash.utils.Endian;

	/**
	 * The <code>Translation</code> is used to store a translation for
	 * a specific language along with some additional information.
	 * 
	 * @author Gabriele Farina <gabriele@sephiroth.it>
	 * 
	 */
	public class Translation
	{
		private var _charset: String;
		private var _information: Dictionary;
		private var _translations: Dictionary;
		
		/**
		 * Construct a <code>Translation</code>.
		 *  
		 * @param	translations	Dictionary of translations
		 * @param	information		Dictionary of information
		 * 
		 */
		public function Translation( translations: Dictionary, information: Dictionary )
		{
			_information = information;
			_translations = translations;
			
			if( _information.hasOwnProperty( 'content-type' ) )
			{
				var ct: String = _information[ 'content-type' ];
				_charset = ct.split( 'charset=' )[ 1 ];
			}
		}
		
		/**
		 * Current translation charset
		 */
		public function get charset(): String
		{
			return _charset;
		}
		
		/**
		 * Retrieve an information given its name.
		 *  
		 * @param	k	The name of the information.
		 * @return 		The information value or null.
		 * 
		 */
		public function getInformation( k: String ): String
		{
			return _information[ k ];
		}
		
		/**
		 * Retrieve a translation for the given key.
		 *  
		 * @param	k	The string to translate.
		 * @return 		The translation or <code>k</code>.
		 * 
		 */
		public function getTranslation( k: String ): String
		{
			if( _translations[ k ] )
			{
				return _translations[ k ];
			}
			
			return k;
		}
		
		/**
		 * Construct a <code>Translation</code> object starting from a
		 * <code>ByteArray</code>.
		 * 
		 * Data must be formatted as a valid <code>.po</code> file.
		 *  
		 * @param	data	The data to be parsed.
		 * @return 			A <code>Translation</code> object corresponding
		 * 					to the passed data. 
		 * 
		 */
		public static function fromByteArray( data: ByteArray ): Translation
		{
			const BE: uint = 3725722773;
    		const LE: uint = 2500072158;
			
			var msg: String;
			var tmsg: String;
			
			var information: Dictionary = new Dictionary();
			var translations: Dictionary = new Dictionary();
			
			var buflen: uint = data.bytesAvailable;
			var magic: uint = data.readUnsignedInt();
			
			// GABRIELE:
			// there's probably a bug somewhere, maybe in my xgettext_g.py generator or
			// somewhere else.
			// Input file is always little endian even if the magic number is
			// big endian.
			data.endian = Endian.LITTLE_ENDIAN;
			
			/*
			switch( magic )
			{
				case BE:
					data.endian = Endian.LITTLE_ENDIAN;
					break;
				
				case LE:
					data.endian = Endian.LITTLE_ENDIAN;
					break;
				
				default:
					throw new Error( "Invalid file (corrupted?)" );
					break;
			}
			*/
			
			var version: uint = data.readUnsignedInt();
            var msgcount: uint = data.readUnsignedInt();
            var masteridx: uint = data.readUnsignedInt();
            var transidx: uint = data.readUnsignedInt();
            
            for( var i: int = 0; i < msgcount; ++i )
            {
            	data.position = masteridx;
            	
            	var mlen: uint = data.readUnsignedInt();
            	var moff: uint = data.readUnsignedInt();
            	var mend: uint = ( moff + mlen );
            	
            	data.position = transidx;
            	
            	var tlen: uint = data.readUnsignedInt();
            	var toff: uint = data.readUnsignedInt();
            	var tend: uint = ( toff + tlen );
            	
            	if( ( mend < buflen ) && ( tend < buflen ) )
            	{
            		data.position = moff;
            		
            		msg = data.readUTFBytes( mlen );
            		
            		data.position = toff;
            		
            		tmsg = data.readUTFBytes( tlen );
            		
            		translations[ msg ] = tmsg;
            	}else
            	{
            		throw new Error( "Invalid file (corrupted!)" );
            	}
            	
            	if( mlen == 0 )
            	{
            		var k: String;
            		var lastk: String;
            		
            		var items: Array = tmsg.split( "\n" );
            		var l: uint = items.length;
            		
            		for( var a: uint = 0; a < l; ++a )
            		{
            			var item: String = items[ a ];
            			
            			if( item.length == 0 )
            			{
            				continue;
            			}
            			
            			if( item.indexOf( ':' ) != -1 )
            			{
            				var chunks: Array = item.split( ":", 2 );
            				k = ( chunks[ 0 ] as String ).toLowerCase();
            				
            				information[ k ] = ( chunks[ 1 ] as String );
            				lastk = k;
            			}else if( lastk )
            			{
            				information[ lastk ] += ( "\n" + item );
            			}
            		}
            	}
            	
            	data.position = 0;
            	masteridx += 8;
            	transidx += 8;
            }
            
			return new Translation( translations, information );
		}

	}
}